package net.pimpas.executor.serviceprovider.impl;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import net.pimpas.executor.serviceprovider.ExecutorServiceProvider;
import net.pimpas.executor.serviceprovider.ExecutorServiceProviderFactory;
import net.pimpas.framework.PimpasFramework;
import net.pimpas.logging.serviceprovider.LoggingServiceProvider;
import net.pimpas.logging.serviceprovider.LoggingServiceProviderFactoryImpl;

public class ExecutorServiceProviderFactoryImpl implements ExecutorServiceProviderFactory {
	
	private static final Map<String, ExecutorServiceProvider> instances = 
		new HashMap<String, ExecutorServiceProvider>();
	private static final LoggingServiceProvider logger = 
		LoggingServiceProviderFactoryImpl.getLoggingServiceProvider(ExecutorServiceProviderFactoryImpl.class);

	private static final ExecutorServiceProvider getInstance( Object... parameters ) {
		// "name" based singleton
		if(parameters.length == 0)
			throw new IllegalArgumentException("U need pass a name for executor service!");
		
		String name = (String) parameters[0];
		
		if(instances.containsKey(name)) return instances.get(name);
		logger.info("[ExecutorServiceProvider]: Finding executor with name ["+name+"]");
		
		// synch block
		synchronized(instances) {
			// double-check
			if(instances.containsKey(name)) {
				logger.info("[ExecutorServiceProvider]: ExecutorProvider Found!!");
				return instances.get(name);
			}
			
			logger.info("[ExecutorServiceProvider]: No ExecuterProvider found for the given name ["+name+"]. Creating one...");
			ExecutorServiceProvider esp = 
				(ExecutorServiceProvider) PimpasFramework.getCurrentInstance().
				getServiceProvider(ExecutorServiceProvider.class, parameters);
			instances.put(name, esp);
			
			return esp;
		}
	}
	
	public static ExecutorServiceProvider getExecutorServiceProvider( Object... parameters ) {
		return new ExecutorServiceProviderFactoryImpl().getServiceProvider(parameters);
	}
	
	public static void terminateExecutor( ExecutorServiceProvider provider ) {
		if(instances.containsValue(provider) && provider.isTerminated()) {
			Iterator<Entry<String, ExecutorServiceProvider>> iterator = instances.entrySet().iterator();
			Entry<String, ExecutorServiceProvider> entry = null;
			boolean found = false;
			while(iterator.hasNext()) {
				entry = iterator.next();
				if(entry.getValue().equals(provider)) {
					found = true;
					break;
				}
			}
			if(found)
				synchronized(instances) {
					instances.remove(entry.getKey());
				}
		}
	}
	
	public ExecutorServiceProvider getServiceProvider(Object... parameters) {
		return getInstance(parameters);
	}
}